<?php
/**
 *生成sitemap的类，
 *你可以配置$baseDIR来控制生成的目录
 *第一次生成需要手动
 *以后只要crontab这个文件就可以了
 *@xinhua
 */
$dir = dirname(dirname(__FILE__));
include($dir.'/__queue_global.php');
include(SERVER_ROOT_PATH.'/include/config/ml_dpoolRsync.php');

class getmap{

    private $oContent;
    private $sitemapFileName;
    private $sitemapNextName;//下一个sitemap的名
    private $indexNextName;//下一个索引节点的名
    private $createGZipFile = false;//暂时不生成gz
    private $baseDIR;
    private $baseURL ="http://meila.com/";//url前缀
    private $urls;
    private $index_xml;
    private $last_index_nd;//最后一个index节点
    private $last_xml;//最后一个sitemap文件
    private $sitemaps;//第一次生成多个sitemap文件数组
    private $is_new_file = false;

    private    $sitemapHeader = '<?xml version="1.0" encoding="UTF-8"?>
                            <urlset
                                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
                                http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
                                xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
                         </urlset>';
    private    $sitemapIndexHeader = '<?xml version="1.0" encoding="UTF-8"?>
                                <sitemapindex
                                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                    xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
                                    http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd"
                                    xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
                              </sitemapindex>';

    public function __construct(){
        $this->baseDIR = SYSDEF_PRIVDATA_ROOT_PATH.'sitemap/';
        $this->oContent = new ml_model_dbContent();

    }
    /**
     * 核心逻辑
     */
    public function main(){

        $time = $this->get_last_time();
        $time = date("Y-m-d H:i:s",$time);
        //获取所有新增的宝贝rid
        $rids = array();
        for ($i = 0;$i<32 ;$i++)
        {
            $this->oContent->get_rid_by_sitemap(Tool_sina::n2tbNo($i),$time);
            $tmp = $this->oContent->get_data();
            if(!empty($tmp))
                $rids = array_merge($rids,$tmp);
        }
        if(empty($rids)){
            die("没有新增的宝贝");
        }else{
            foreach ($rids as $value) {
                //添加url
                if(!empty($value['rid'])){
                    $value="http://meila.com/show_goods/".$value['rid'];
                    $this->addUrl($value, date('c'), 'daily');
                }

            }
        }
        $this->get_last_sitemap();
        $count = count($this->last_xml);

        if($count+count($rids)>=50000){//大于50000条生成新的xml文件
            //创建sitemap
            $this->createSitemap();
            $this->writeSitemap();
            $this->addSitemapIndex();//ok
            $this->is_new_file = true;
            echo "new file done\n";
        }else{//否者追加
            $this->updateSitemap();//ok
            $this->updateSitemapIndex();//ok
            echo "add done\n";
        }
        $this->rsync_to_front();
        echo 'rsync_done';

    }

    /**
     * 从索引文件得到最后一个sitemap，最后修改的时间
     */
    private function get_last_time(){
        if(!is_file(SERVER_ROOT_PATH."/sitemap_index.xml")){//没有xml索引
            die("no index_xml");
        }
        else{
            $this->index_xml = simplexml_load_file(SERVER_ROOT_PATH."/sitemap_index.xml");
            $tmp = (array)$this->index_xml;
            $this->last_index_nd = array_pop($tmp['sitemap']);
            
            return strtotime($this->last_index_nd->lastmod);
        }
    }
    /**
     * 获得最后一个sitemap文件
     */
    private function get_last_sitemap(){

        for ($j = 1000; $j >1; $j--) {//索引文件最多1000个
            if(is_file($this->baseDIR."sitemap".$j.".xml")){
                $this->last_xml = simplexml_load_file($this->baseDIR."sitemap".$j.".xml");
                $this->sitemapFileName = "sitemap".$j.".xml";//当前sitemap名
                $this->indexNextName = $this->baseURL."sitemap/sitemap".($j+1).".xml";//如果>5万，下一个sitemap的url名
                $this->sitemapNextName ="sitemap".($j+1).".xml";//如果>5万，下一个sitemap的文件名
                break;
            }
        }

        if(empty($this->last_xml)){//没有xml，第一次的话得手动生成下
            die("没有xml文件或者没有读权限");
        }
        else{//第一次生成后，每小时更新一次最后的xml
            return $this->last_xml;
        }
    }
    /**
     * 使用这个方法可以同时添加多个url
     * 每个链接有4个参数可以设置
     * @param array of arrays of strings $urlsArray
     */
    public function addUrls($urlsArray) {
        if (!is_array($urlsArray))
        die('参数$aURLs需要时数组');
        foreach ($urlsArray as $url) {
            $this->addUrl(isset ($url[0]) ? $url[0] : null,
            isset ($url[1]) ? $url[1] : null,
            isset ($url[2]) ? $url[2] : null,
            isset ($url[3]) ? $url[3] : null);
        }
    }
    /**
     * 使用这个方法每次添加一个连接到sitemap中
     * @param string $url URL
     * @param string $lastModified 当被修改时，使用ISO 8601
     * @param string $changeFrequency 搜索引擎抓取信息的频率
     * @param string $priority 你网站中连接的权重
     */
    public function addUrl($url, $lastModified = null, $changeFrequency = null, $priority = null) {
        if ($url == null)
        die("URL 是必填项.");
        $urlLenght = extension_loaded('mbstring') ? mb_strlen($url) : strlen($url);
        if ($urlLenght > 2048)
        die("URL的长度不能超过2048");
        $tmp = array();
        $tmp['loc'] = $url;
        if (isset($lastModified)) $tmp['lastmod'] = $lastModified;
        if (isset($changeFrequency)) $tmp['changefreq'] = $changeFrequency;
        if (isset($priority)) $tmp['priority'] = $priority;
        $this->urls[] = $tmp;
    }
    /**
     * 在内存中创建sitemap.
     */
    public function createSitemap() {
        if (!isset($this->urls))
        die("请先加载addUrl方法.");    
        foreach(array_chunk($this->urls,50000) as $sitemap) {
            $xml = new SimpleXMLElement($this->sitemapHeader);    
            foreach($sitemap as $url) {
                $row = $xml->addChild('url');
                $row->addChild('loc',htmlspecialchars($url['loc'],ENT_QUOTES,'UTF-8'));
                if (isset($url['lastmod'])) $row->addChild('lastmod', $url['lastmod']);
                if (isset($url['changefreq'])) $row->addChild('changefreq',$url['changefreq']);
                if (isset($url['priority'])) $row->addChild('priority',$url['priority']);
            }
            if (strlen($xml->asXML()) > 10485760)
            die("sitemap文件的大小不能超过10MB (10,485,760)");
            $this->sitemaps[] =$xml->asXML();

        }
        unset($this->urls);
        if (sizeof($this->sitemaps) > 1000)
        die("sitemap索引文件最多可以包含1000条索引.");
        if (sizeof($this->sitemaps) > 1) {
            for($i=0; $i<sizeof($this->sitemaps); $i++) {
                $this->sitemaps[$i] = array(
                str_replace(".xml", ($i+1).".xml.gz", $this->sitemapFileName),
                $this->sitemaps[$i]
                );
            }
            $xml = new SimpleXMLElement($sitemapIndexHeader);
            foreach($this->sitemaps as $sitemap) {
                $row = $xml->addChild('sitemap');
                $row->addChild('loc',$this->baseURL.htmlentities($sitemap[0]));
                $row->addChild('lastmod', date('c'));
            }
            $this->sitemapFullURL = $this->baseURL.$this->sitemapIndexFileName;
            $this->sitemapIndex = array(
            $this->sitemapIndexFileName,
            $xml->asXML());
        }
        else {
            if ($this->createGZipFile)
            $this->sitemapFullURL = $this->baseURL.$this->sitemapNextName.".gz";
            else
            $this->sitemapFullURL = $this->baseURL.$this->sitemapNextName;
            $this->sitemaps[0] = array(
            $this->sitemapNextName,
            $this->sitemaps[0]);
        }
    }
    /**
     * 写sitemap文件
     * @access public
     */
    public function writeSitemap() {
        if (!isset($this->sitemaps))
        die("请先加载createSitemap方法.");
        if (isset($this->sitemapIndex)) {
            $this->_writeFile($this->sitemapIndex[1], $this->baseDIR, $this->sitemapIndex[0]);
            foreach($this->sitemaps as $sitemap) {
                $this->_writeGZipFile($sitemap[1], $this->baseDIR, $sitemap[0]);
            }
        }
        else {
            $this->_writeFile($this->sitemaps[0][1], $this->baseDIR, $this->sitemaps[0][0]);
            if ($this->createGZipFile)
            $this->_writeGZipFile($this->sitemaps[0][1], $this->baseDIR, $this->sitemaps[0][0].".gz");
        }
    }
    /**
     * 更新sitemap文件
     * @access public
     */
    public function updateSitemap() {

        $xml = new SimpleXMLElement($this->sitemapHeader);
        $tmp = (array)$this->last_xml;

        foreach($tmp['url'] as $url) {//原有的
            $row = $xml->addChild('url');
            $row->addChild('loc',htmlspecialchars($url->loc,ENT_QUOTES,'UTF-8'));
            if (isset($url->lastmod)) $row->addChild('lastmod', $url->lastmod);
            if (isset($url->changefreq)) $row->addChild('changefreq',$url->changefreq);
            if (isset($url->priority)) $row->addChild('priority',$url->priority);

        }
        unset($tmp);
        unset($this->last_xml);//释放内存(试了下大约可以释放掉10M内存)

        if(!empty($this->urls)){
            foreach($this->urls as $url) {//新发布的
                $row = $xml->addChild('url');
                $row->addChild('loc',htmlspecialchars($url['loc'],ENT_QUOTES,'UTF-8'));
                if (isset($url['lastmod'])) $row->addChild('lastmod', $url['lastmod']);
                if (isset($url['changefreq'])) $row->addChild('changefreq',$url['changefreq']);
                if (isset($url['priority'])) $row->addChild('priority',$url['priority']);
            }
        }
        unset($this->urls);

        if (strlen($xml->asXML()) > 10485760)
        die("sitemap文件的大小不能超过10MB (10,485,760)");
        $this->_writeFile($xml->asXML(), $this->baseDIR, $this->sitemapFileName);

    }

    /**
     * 更新index文件
     * @access public
     */
    public function updateSitemapIndex() {

        $this->last_index_nd->lastmod = date("c");
        $this->_writeFile($this->index_xml->asXML(), SERVER_ROOT_PATH."/", "sitemap_index.xml");

    }
    /**
     * 添加index文件
     * @access public
     */
    public function addSitemapIndex() {
        $xml = new SimpleXMLElement($this->sitemapIndexHeader);
        $tmp = (array)$this->index_xml;
        foreach($tmp['sitemap'] as $url) {
            $row = $xml->addChild('sitemap');
            $row->addChild('loc',htmlspecialchars($url->loc,ENT_QUOTES,'UTF-8'));
            $row->addChild('lastmod', $url->lastmod);
        }
        $row = $xml->addChild('sitemap');
        $row->addChild('loc',htmlspecialchars($this->indexNextName,ENT_QUOTES,'UTF-8'));
        $row->addChild('lastmod', date("c"));

        if (count($xml['sitemap']) > 1000)
        die("索引文件不能大于1000条记录");
        $this->_writeFile($xml->asXML(),SERVER_ROOT_PATH."/", "sitemap_index.xml");

    }

    /**
     * 保存文件
     * @param string $content
     * @param string $filePath
     * @param string $fileName
     * @return bool
     * @access private
     */
    private function _writeFile($content, $filePath, $fileName) {
        chmod($filePath.$fileName,0777);
        $file = fopen($filePath.$fileName, 'w+');
        fwrite($file, $content);    
        return fclose($file);
    }
    /**
     * 保存 GZipped文件.
     * @param string $content
     * @param string $filePath
     * @param string $fileName
     * @return bool
     * @access private
     */
    private function _writeGZipFile($content, $filePath, $fileName) {
        $file = gzopen($filePath.$fileName, 'w+');
        gzwrite($file, $content);
        return gzclose($file);
    }
    /**
     * 数组转换成xml字符串
     * 留着备用，这次没用上
     */
    private function array_to_xml($array) {
        if(is_object($array)){
            $array = get_object_vars($array);
        }
        $xml = '';
        foreach($array as $key => $value){
            $_tag = $key;
            $_id = null;
            if(is_numeric($key)){
                $_tag = 'item';
                $_id = ' id="' . $key . '"';
            }
            $xml .= "<{$_tag}{$_id}>";
            $xml .= (is_array($value) || is_object($value)) ? $this->array_to_xml($value) : htmlentities($value);
            $xml .= "</{$_tag}>";
        }
        return $xml;
    }
    
    private function rsync_to_front()
    {
        ml_tool_distrsync::rsync(SERVER_ROOT_PATH , MEILA_RSYNC_TO_DIST_MOD_SRC , 'sitemap_index.xml');
        
        $filename = $this->is_new_file ? $this->sitemapNextName : $this->sitemapFileName;
        echo 'rsync '.$filename."\n";
        ml_tool_distrsync::rsync(SYSDEF_PRIVDATA_ROOT_PATH , MEILA_RSYNC_TO_DIST_MOD_SRC , 'sitemap/'.$filename);
    }

}

$obj = new getmap();
$obj->main();
?>